package cardsbody {
	import Classes.CLoader;
	import Classes.pi_events;
	
	import UIFree.ObjectEvent;
	import UIFree.controls.uif_label;
	import UIFree.uif_component;
	
	import UIUtils.uif_util;
	
	import api_servers.pi_servers;
	
	import editor.pi_cardbody;
	
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.BitmapDataChannel;
	import flash.display.BlendMode;
	import flash.display.DisplayObject;
	import flash.display.LoaderInfo;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.geom.ColorTransform;
	import flash.geom.Matrix;
	import flash.geom.Matrix3D;
	import flash.geom.PerspectiveProjection;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	import flash.geom.Vector3D;
	import flash.net.URLRequest;
	import flash.system.LoaderContext;
	import flash.utils.ByteArray;
	
	import templates.pi_effects;
	

	public class pi_pngcard extends pi_cardbody {
		protected var _label		: uif_label;
		protected var _bitmap		: Bitmap;
		protected var _photoBitmap	: Bitmap;
		protected var _photoLayer	: Sprite;
		protected var _photoTop		: Sprite;
		protected var _effectObj	: Object;
		protected var _effect		: *;
		protected var _effectLoader	: CLoader;
		protected var _jpgBitmap	: Bitmap;
		
		public function pi_pngcard(parent:uif_component, 
									ax:int=0, ay:int=0,
									awidth: int=0, aheight: int=0,
									styleName: String='') {
			super(parent, ax, ay, awidth, aheight, '');
			_effect		= null;
			_effectObj	= null;
			_label		= new uif_label(this, 0, 0, awidth, aheight, 'maskHelp');
			_label.visible = false;
			_photo.visible = false;
			_mask.visible  = false;
			
			_photoLayer	= new Sprite();
			_photoTop	= new Sprite();
			_photoBitmap = new Bitmap();
			_photoLayer.addChild(_photoBitmap);
			_photoTop.addChild(_photoLayer);
			_bitmap		= new Bitmap();
			_bitmap.smoothing = true;
			addChild(_bitmap);

			_effectLoader = new CLoader(this, '', doLoadEffect);
			_effectLoader.visible = false;
			
			_photoTop.transform.perspectiveProjection = new PerspectiveProjection();
		}
		
		protected function apply3D(): void {
			if (card_photo.loaded) {
				if (maskInfo.r3d && _photoBitmap) {
					var mat: Matrix3D = new Matrix3D();
					var c: Point = new Point(_photoBitmap.width/2, _photoBitmap.height/2);
					var v: Vector3D = new Vector3D(maskInfo.r3d[0], maskInfo.r3d[1], maskInfo.r3d[2]);
					v.normalize();
					mat.appendTranslation(-c.x, -c.y, 0);
					mat.appendRotation(maskInfo.r3d[3], v);
					mat.appendTranslation(c.x, c.y, 0);
					_photoLayer.transform.matrix3D = mat;
				} else _photoLayer.transform.matrix = new Matrix();
			}
		}
		
		protected function apply3DProjection(): void {
			if (card_mask.source.loaded) {
				var center: Point = new Point(contentSize.x / 2, contentSize.y / 2);
				if (maskInfo.r3d) {
					center.x = contentSize.x * maskInfo.r3d[4];
					center.y = contentSize.y * maskInfo.r3d[5];
				}
				_photoTop.transform.perspectiveProjection.projectionCenter = center;
			}
		}
		
		override protected function updateFromInfo(): void {
			apply3DProjection();
			apply3D();
			_paintToBitmap();
			super.updateFromInfo();
		} 
		
		override protected function doLoadPhoto(e: Event): void {
			_label.visible = false;
			if (_photoBitmap.bitmapData) _photoBitmap.bitmapData.dispose();
			_photoBitmap.bitmapData = new BitmapData(_photo.contentLoaderInfo.width, _photo.contentLoaderInfo.height);
			_photoBitmap.smoothing = true;
			_photoBitmap.bitmapData.draw(_photo);
			apply3D();
			super.doLoadPhoto(e);
		}
		
		override protected function photoFromSendCard(): DisplayObject {
			return _photoBitmap;
		} 
		
		override protected function doLoadedComponent(): void {
			if (loaded) {
				_paintToBitmap();
				doUpdateEffect();
			}
			super.doLoadedComponent();
		}
		
		override public function get loaded(): Boolean {
			return super.loaded && ((pj.requireLoaded == photo_inject.MASK_LOAD_ONLY)
			                    || (!_effectObj) || (_effectObj.id <= 0) || (_effectLoader.loaded)); 
		}
		
		public function get effectID(): int {
			return (_effectObj != null)?_effectObj.id:0;
		}
		
		override protected function maskResize(): void {
			super.maskResize();
			_paintToBitmap();
		}
		
/*		
		override protected function resetPhoto(a_photo: CLoader): void {
			super.resetPhoto(a_photo);
		}*/
		
		protected function doLoadEffect(e: Event): void {
			if (_effect != null) _effect.dispose();
			var PJFilter: * = (e.target as LoaderInfo).applicationDomain.getDefinition(_effectObj.className?_effectObj.className:'PJFilter');
			_effect = new PJFilter();
			doLoadedComponent();
		}
		
		public function initEffect(a_effectID: int): void {
			if (a_effectID > 0) {
				_effectObj = pi_effects.list[pi_effects.effectIndex(a_effectID)];
				var fileURL: String = pi_servers.EFFECTS_URL + (_effectObj.file?_effectObj.file:('f' + effectID + '.swf')) + '?' + pj.externalserver.vars['ver'];
				_effectLoader.load(new URLRequest(fileURL), new LoaderContext(true));
			} else {
				if (_effect != null) _effect.dispose();
				_effectLoader.unload();
				_effect 	= null;
				_effectObj 	= null;
			}
		}
		
		protected function doUpdateEffect(e: Event=null): void {
			if (_effect) { 
				var size: Point = contentSize;
				_effect.x = _bitmap.x;
				_effect.y = _bitmap.y;
				var scale: Number = _bitmap.width / size.x;
				if (scale < 0.8) scale = 0.8;
				_effect.scaleX = scale;
				_effect.scaleY = scale;
				_effect.parameters = {parent: this, bounds: new Rectangle(0, 0, _bitmap.width / scale, _bitmap.height / scale), info: _effectObj};
			}
		}
		
		public function get contentSize(): Point {
			return new Point(_mask.source.contentLoaderInfo.width, _mask.source.contentLoaderInfo.height);
		}
		
		override protected function getPackInfo(a_photoMatrix: Matrix, photoURL: String=''): String {
			var result: String = super.getPackInfo(a_photoMatrix, photoURL);
			if (_effect) {
				if (_effect['packInfo']) result += '~' + _effect.packInfo();
				else result += '~' + effectID;
			} 
			return result;
		}
		
		public function get bitmap(): Bitmap {
			return _bitmap;
		}
		
		protected function _paintToBitmap(): void {
			if (loaded) {
				var inner: Rectangle = getInner();
				var bmRect: Rectangle = EnterHere(contentSize);
				if (_bitmap.bitmapData) _bitmap.bitmapData.dispose();
				_bitmap.bitmapData = new BitmapData(bmRect.width, bmRect.height, true, 0xFFFFFF);
				_bitmap.x = (inner.width - bmRect.width) / 2;
				_bitmap.y = (inner.height - bmRect.height) / 2;
				paintToBitmap(_bitmap);
/*				
				var size  : Point = contentSize;
				var nsize : Point;
				var inner : Rectangle = getInner();
				var matrix: Matrix;
				var scale : Number = 1;
				
				if (size.x - inner.width > size.y - inner.height) scale = inner.width / size.x;
				else scale = inner.height / size.y;
				if (scale > 1) scale = 1;
				
				nsize = new Point(size.x * scale, size.y * scale);
				if (nsize.x && nsize.y) {
					if (_bitmap.bitmapData) _bitmap.bitmapData.dispose();
					_bitmap.bitmapData = new BitmapData(nsize.x, nsize.y, true, 0xFFFFFF);
					  
					if (_photoBitmap.bitmapData) {
						matrix = _photoMatrix.clone();
						matrix.translate(_maskInfo.pos.x, _maskInfo.pos.y);
						matrix.scale(scale, scale);
						_bitmap.bitmapData.draw(_photoBitmap, matrix, _maskInfo.colors, null, null, true);
					}
					
					matrix = new Matrix();
					matrix.scale(scale, scale);
	
					(_mask.source.content as Bitmap).smoothing = true;
					_bitmap.bitmapData.draw(_mask.source, matrix, null, null, null, true);
					_bitmap.x = (inner.width - nsize.x) / 2;
					_bitmap.y = (inner.height - nsize.y) / 2;
					dispatchEvent(new ObjectEvent(pi_events.PAINTTOBITMAP, {matrix: matrix, bitmap: _bitmap}));
				}*/
			}
		}
		
		protected function paintoPhoto(a_bitmap: Bitmap, scale : Number): void {
			var matrix	: Matrix;
			if (_photoBitmap.bitmapData) {
				matrix = _photoMatrix.clone();
//				matrix.translate(_maskInfo.pos.x, _maskInfo.pos.y);
//				matrix.scale(scale, scale);
				_photoBitmap.transform.matrix = matrix;
				var ct: ColorTransform = new ColorTransform();
				ct.concat(_maskInfo.colors);
				ct.concat(colorsExt);
				var b_matrix: Matrix = new Matrix();
				b_matrix.translate(_maskInfo.pos.x, _maskInfo.pos.y);
				b_matrix.scale(scale, scale);
				a_bitmap.bitmapData.draw(_photoTop, b_matrix, ct, null, null, true);
			}			
		}
		
		public function paintToBitmap(a_bitmap: Bitmap): void {
			var nsize 	: Point;
			var bmRect 	: Rectangle = a_bitmap.bitmapData.rect;
			var scale 	: Number = bmRect.width / contentSize.x;
			var l_mat	: Matrix = new Matrix(); 
			l_mat.scale(scale, scale);
			paintoPhoto(a_bitmap, scale);
			if ((scale != 1) && !_maskInfo.jpg) (_mask.source.content as Bitmap).smoothing = true;
			
			a_bitmap.bitmapData.draw(templateImage, l_mat, _tmplColors, null, null, true);
			dispatchEvent(new ObjectEvent(pi_events.PAINTTOBITMAP, {matrix: l_mat, bitmap: a_bitmap}));
		}
		
		protected function get templateImage(): DisplayObject {
			return (_maskInfo.jpg?_jpgBitmap:_mask.source); 
		}
		
		public function asBytes(maxSize: Point = null): ByteArray {
			
			var r_size: Rectangle;
			if (maxSize) {
				maxSize = (maxSize != null)?maxSize:contentSize;
				r_size = uif_util.EnterHere(new Rectangle(0, 0, maxSize.x, maxSize.y), contentSize);
			} else r_size = new Rectangle(0, 0, contentSize.x, contentSize.y)
		
			var bitmap: Bitmap = asBitmap(new Point(r_size.width, r_size.height));
			var bytes: ByteArray = pj.encodeFromJPG(bitmap.bitmapData);
			bitmap.bitmapData.dispose();
			return bytes;
		}
		
		public function asBitmap(size: Point = null): Bitmap {
			if (size == null) size = contentSize;
			var bitmap: Bitmap = new Bitmap(new BitmapData(size.x, size.y, true, 0xFFFFFF));
			paintToBitmap(bitmap);
			return bitmap;
		}
		
		override public function infoFromCollector(): String {
			if (bmpContent()) {
				var flips: Point = (app as pi_app).getEvent(pi_events.GET_FLIPS, pi_events.FLIPSDATA);
				
				var center: Point = new Point(_maskInfo.pos.width / 2, _maskInfo.pos.height / 2);
				var mat: Matrix = _photoMatrix.clone();
				mat.invert();
				var cs: Point = contentSize;
				var pos2: Point = mat.transformPoint(center);
				
				return _maskInfo.toString() +
					'&tid=' + _maskInfo.id + 
					'&ts=' + cs.x  + ',' + cs.y +
					'&photo_pos2=' + pos2.x  + ',' + pos2.y +
					'&scale=' + Math.abs(_photo.scaleX) +
					(flips?('&flips=' + flips.x + ',' + flips.y):'&flips=1,1') + 
					'&rotation=' + _photo.rotation +
					'&img=' + _photo.sourceUrl.replace('http://', '') + 
					'&ext=' + packExtend();
			} else return super.infoFromCollector();
		}
		
/*		override public function applyPhotoMatrix(matrix: Matrix): void {
			super.applyPhotoMatrix(matrix);
			if (matrix) _photo.transform.matrix = matrix;
		}*/
		
		protected function calcAlphaRect(): Rectangle {
			var bitmapData: BitmapData = new BitmapData(card_mask.source.contentLoaderInfo.width, card_mask.source.contentLoaderInfo.height, false, 0);
			bitmapData.draw(templateImage, null, new ColorTransform(1, 1, 1, 3, 0, 0, 0, -240), BlendMode.ERASE);
			
			var alphaRect: Rectangle = bitmapData.getColorBoundsRect(0xFFFFFFFF, 0, true);
			alphaRect.inflate(alphaRect.width * 0.05, alphaRect.height * 0.05);

//			bitmapData.fillRect(alphaRect, 0);
			bitmapData.dispose();
			alphaRect.width = Math.floor(alphaRect.width);
			alphaRect.height = Math.floor(alphaRect.height);
			_maskInfo.pos = alphaRect;
/*
			var bitmap: Bitmap = new Bitmap(bitmapData);
			bitmap.alpha = 0.9;
			addChild(bitmap);*/
			
			return alphaRect;
		}
		
		protected function loadAsJPG(): void {
			var l_tmpl: CLoader;
			var l_mask: CLoader;
			
			function l_doLoad(e: Event): void {
				if (l_tmpl.loaded && l_mask.loaded) {
					var size: Point = new Point(l_tmpl.contentLoaderInfo.width, l_tmpl.contentLoaderInfo.height);
					
					if (_jpgBitmap) _jpgBitmap.bitmapData.dispose();
					else _jpgBitmap = new Bitmap();
					_jpgBitmap.bitmapData = new BitmapData(size.x, size.y); 
					_jpgBitmap.bitmapData.draw(l_tmpl);
					
					var bmdMask: BitmapData = new BitmapData(size.x, size.y, true, 0xFFFFFF);
					bmdMask.draw(l_mask);
					_jpgBitmap.bitmapData.copyChannel(bmdMask, bmdMask.rect, new Point(0, 0), BitmapDataChannel.BLUE, BitmapDataChannel.ALPHA);
					_jpgBitmap.smoothing = true;
					
					function l_doComplete(e: Event): void {
						_mask.source.contentLoaderInfo.removeEventListener(Event.COMPLETE, l_doComplete);
						bmdMask.dispose();
						l_mask.unload();
						l_tmpl.unload();
						removeChild(l_tmpl);
						removeChild(l_mask);
					}
					_mask.source.contentLoaderInfo.addEventListener(Event.COMPLETE, l_doComplete);
					_mask.source.loadBytes(l_tmpl.contentLoaderInfo.bytes, new LoaderContext(false));
				}
			}

			l_tmpl = new CLoader(this, pi_servers.MROOT_URL + 'JPG/' + _maskInfo.id + '.jpg', l_doLoad, 0, 0, new LoaderContext(true));
			l_mask = new CLoader(this, pi_servers.MROOT_URL + 'JPG/' + _maskInfo.id + 'm.jpg', l_doLoad, 0, 0, new LoaderContext(true));
			l_tmpl.visible = false;
			l_mask.visible = false;
		}
		
		override protected function loadMask(): void {
			if (_maskInfo.jpg) loadAsJPG();
			else _mask.loadSource(_maskInfo.url);
		}
		
		override protected function doLoadMask(e: Event): void {
			if (!_maskInfo.pos) _maskInfo.pos = calcAlphaRect();
			super.doLoadMask(e);
		}

		override public function unloadAll(): void {
			if ((_bitmap != null) && (_bitmap.bitmapData)) _bitmap.bitmapData.dispose();
			initEffect(0);
			super.unloadAll();
		}
	}
}